# -*- coding: utf-8 -*-
"""
Created on Fri Dec 28 17:27:54 2018

@author: 刘丹

胎压数据模拟，主要生成2个表数据
①胎压温度监测表，记录胎压和温度
②位置表，记录胎压的位置TP_location
"""

import pandas as pd
import numpy as np
import random
import datetime
from math import radians, cos, sin, asin, sqrt
from pao import log
from pao.data import process_db
from gov.data_process.data import DataProcess
import matplotlib.pyplot as plt

#数据列含义：轮胎位置0-3，胎压，温度，慢漏，快漏，传感器低电，轮胎过热，过压，欠压，传感器失效
columns=['TPID','date','tirePos','pressure','temperature','slowLeak','fastLeak','lowBattery'
         ,'overHeat','overPressure','lowPressure','sensorFailed']

class TP_Sim_Data(DataProcess):
    
    num = 2880 #30s采集一次，一天采集24*60*60/30=2880次
    
    def __init__(self,db_addr,db_port,date,destination_loc):
        DataProcess.__init__(self,db_addr,db_port)
        self.date=date
        self.destination_loc=destination_loc
    
    def geodistance(self,lng1,lat1,lng2,lat2):
        lng1, lat1, lng2, lat2 = map(radians, [lng1, lat1, lng2, lat2])
        dlon=lng2-lng1
        dlat=lat2-lat1
        a=sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 
        dis=2*asin(sqrt(a))*6371*1000
        return dis
    
    def dirve_time_point(self):
        #模拟一辆车一天中哪些时间处于驾驶状态，驾驶的时间范围
        #以30s采集一次数据，一天24小时，有2880个时点可以采集数据
        #返回数据为[[开始采集的时点],[结束采集的时点]]
        drive_times=round(5*(random.random()))+1
        points=random.sample(range(self.num-30),drive_times*2)
        points.sort()
        start_points=[]
        end_points=[]
        #对其合法性进行修改
        start_points.append(points[0])
        for i in range(1,drive_times*2):
            if i<drive_times*2-1 and points[i]-start_points[-1]<30:
                i=i+1
            elif i==drive_times*2-1 and points[i]-start_points[-1]<30:
                end_points.append(self.num-1)
            elif i==drive_times*2-1 and points[i] == start_points[-1]:
                end_points.append(self.num-1)
            else:
                end_points.append(points[i])
                if i == drive_times*2-1:
                    break
                start_points.append(points[i+1])
                if i == drive_times*2-2 :
                    end_points.append(self.num-1)
                    break 
                i=i+1
        res=[start_points,end_points]
        return res

    def temperature_change(self,n,Upper_T):
        #模拟单一轮胎从开始的温度变化
        temper=[]
        if self.date.month in [4,5,6,7,8,9,10,11]:
            start_T=random.randint(30,55)
        else:
            start_T=random.randint(10,35)
        temper.append(start_T)
        par_a=round(random.random(),2)
        for i in range(1,n) :
            add_tep=2*round(random.random(),2)
            if temper[-1]+add_tep>Upper_T-(3+5*par_a):
                temper.append((temper[-1])+(0.1*round(random.random(),2)-0.05))
            else:
                temper.append(temper[-1]+add_tep)
        return temper
                
    def pressure_change(self,n,Stand_P):
        #模拟单一轮胎压力变化
        pres=[]
        if self.date.month in [4,5,6,7,8,9,10,11]:
            Stand_P=Stand_P-0.1*round(random.random(),2)
        else:
            Stand_P=Stand_P+0.2*round(random.random(),2)
        for i in range(n):
            tep=0.01*round(random.random(),2)-0.005
            pres.append(Stand_P+tep)
        return pres
        
    def sigle_car_normal(self,Stand_P,Upper_T,tynum):
        #生成单一车辆四个轮胎一天的温度、压力和位置数据
        dates=pd.date_range(self.date.strftime("%Y-%m-%d"),periods=self.num,freq='30s')
        points=self.dirve_time_point()
        #生成单一车辆四个轮胎一天的温度和压力数据
        tp_df=pd.DataFrame(columns=['date','pressure','temperature','tirepos'])
        for t in range(4):
            pres=[0 for x in range(self.num)]
            temper=[0 for x in range(self.num)]
            tirpos=[t for x in range(self.num)]
            for i in range(len(points[0])):
                n=points[1][i]-points[0][i]
                tep_temper=self.temperature_change(n,Upper_T)
                tep_pres=self.pressure_change(n,Stand_P)
                temper[points[0][i]:points[1][i]]=tep_temper            
                pres[points[0][i]:points[1][i]]=tep_pres
            tep_df=pd.DataFrame({'date':dates,'pressure':pres
                                ,'temperature':temper,'tirepos':tirpos})
            tp_df=tp_df.append(tep_df)
        #生成位置数据
        loc_date=[]
        loc_lng=[]
        loc_lat=[]
        loc_date.append(dates[points[0][0]-1])
        loc_date.append(dates[points[1][0]-1])
        #查找前一天的停放位置
        yesterday=self.date+ datetime.timedelta(days = -1)
        tep_dates=pd.date_range(yesterday.strftime("%Y-%m-%d"),periods=25,freq='H')
        start_loc=[]
        def process_func(db):
            nonlocal start_loc
            collection_TP=db['TP_location']
            cur_ty=collection_TP.find({'TPID':tynum,'date':{'$gte': tep_dates[0], '$lt': tep_dates[-1]}})
            start_loc=list(cur_ty[:])
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        start_df=pd.DataFrame(start_loc)
        if start_df.empty:
            tep_index=random.randint(0,len(self.destination_loc))
            loc_lng.append(self.destination_loc['LONGITUDE'].iloc[tep_index])
            loc_lat.append(self.destination_loc['LATITUDE'].iloc[tep_index])
        else:
            start_df=start_df.sort_values(by='date',ascending=False)
            loc_lng.append(start_df['LONGITUDE'].iloc[0])
            loc_lat.append(start_df['LATITUDE'].iloc[0])
        loc_lng.append(0)
        loc_lat.append(0)
        for i in range(len(points[0])):
            if i==len(points[0])-1:
                pass
            else:
                loc_date.append(dates[points[0][i]-1])
                loc_date.append(dates[points[1][i]-1])
            n=(points[1][i]-points[0][i])*30/60/60 #车子行驶的时长，单位是小时
            t=21
            while t>20:
                t=1
                tep_index=random.randint(0,len(self.destination_loc))
                lng_tep=self.destination_loc['LONGITUDE'].iloc[tep_index]
                lat_tep=self.destination_loc['LATITUDE'].iloc[tep_index]
                distance=self.geodistance(loc_lng[-2],loc_lat[-2],lng_tep,lat_tep)
                while distance > n*80000 or distance<n*20000:
                    t=t+1
                    if distance > n*80000 :
                       lng_tep=lng_tep-0.3*(lng_tep-loc_lng[-2])
                       lat_tep=lat_tep-0.3*(lat_tep-loc_lat[-2])
                    elif distance < n*20000 :
                       lng_tep=lng_tep+0.3*(lng_tep-loc_lng[-2])
                       lat_tep=lat_tep+0.3*(lat_tep-loc_lat[-2])
                    distance=self.geodistance(loc_lng[-2],loc_lat[-2],lng_tep,lat_tep)
                    if t>20:
                        break
            loc_lng.append(lng_tep)
            loc_lng.append(0)
            loc_lat.append(lat_tep)
            loc_lat.append(0)
        loc_lng.pop(-1)
        loc_lng.pop(-2)
        loc_lat.pop(-1)
        loc_lat.pop(-2)
        if len(points[0])>1:
            for j in range(0,(len(points[0])-1)):
                loc_lng[j*2+1]=loc_lng[j*2+2]
                loc_lat[j*2+1]=loc_lat[j*2+2]
        loc_df=pd.DataFrame({'date':loc_date,'LONGITUDE':loc_lng,'LATITUDE':loc_lat})
        res=[tp_df,loc_df]
        return res
   
    def insert_TP_monitoring(self):
        #获取ty_num及其对应的标准压力和温度上限
        ty_basic=''
        def process_func(db):
            nonlocal ty_basic
            collection_TP=db['TP_stand']
            cur_ty=collection_TP.find({})
            ty_basic=list(cur_ty[:])
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        ty_basic_df=pd.DataFrame(ty_basic)
        log('TP_Monitoring和TP_location数据插入','插入数据时间为:%s'%(self.date.strftime("%Y-%m-%d")))
        for i in range(len(ty_basic_df)):
            if (i+1)%10 == 0 :
                print('正在生成第',i+1,'个车的数据')
            Stand_P=ty_basic_df['Stand_P'].iloc[i]
            Upper_T=ty_basic_df['Upper_T'].iloc[i]
            ty_num=int(ty_basic_df['TPID'].iloc[i])
            data_df=self.sigle_car_normal(Stand_P,Upper_T,ty_num)
            tp_df=data_df[0]
            loc_df=data_df[1]
            #插入胎压温度，压力
            def process_func(db):
                for t in range(self.num*4):
                    insert_data={
                            'TPID':ty_num
                            ,'date':tp_df['date'].iloc[t]
                            ,'tirePos':tp_df['tirepos'].iloc[t]
                            ,'pressure':tp_df['pressure'].iloc[t]
                            ,'temperature':tp_df['temperature'].iloc[t]
                            ,'slowLeak':False
                            ,'fastLeak':False
                            ,'lowBattery':False
                            ,'overHeat':False
                            ,'overPressure':False
                            ,'lowPressure':False
                            ,'sensorFailed':False
                            }
                    collection_TP_mon=db['TP_Monitoring']
                    collection_TP_mon.insert(insert_data)
            process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
            #插入位置数据 
            def process_func(db):
                for t in range(len(loc_df)):
                    insert_data={
                            'TPID':ty_num
                            ,'date':loc_df['date'].iloc[t]
                            ,'LONGITUDE':loc_df['LONGITUDE'].iloc[t]
                            ,'LATITUDE':loc_df['LATITUDE'].iloc[t]
                            }
                    collection_TP_mon=db['TP_location']
                    collection_TP_mon.insert(insert_data)
            process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
            

'''
loc_datas=pd.read_csv(u'C:\\Users\\刘丹\\Desktop\\YMQ\\电流环_ymq\\monidata1\\10Wnh_location.csv',engine='python')
test=TP_Sim_Data(db_addr='localhost',db_port=27017,date=datetime.datetime.now(),destination_loc=loc_datas)
time1=datetime.datetime.now()
test.insert_TP_monitoring()
time2=datetime.datetime.now()
print('插入一天的数据耗时：',time2-time1)
'''